<template>
  <div className="root">
    <div className="left_box"></div>
    <div className="center_box">
      <div className="canvas_box">
        <canvas id="myCanvas" width="1600" height="900" ref="myCanvas"></canvas>
      </div>
    </div>
    <div className="right_box"></div>
  </div>
</template>

<script setup>
import {onMounted, ref} from "vue";

const myCanvas = ref()
let bg = new URL('../assets/images/photo/拼图1.png', import.meta.url).href
let imgBox2 = [
  {
    id: 1,
    src: new URL('../assets/images/photo/1.png', import.meta.url).href,
    x: 13,
    y: 261,
    pointX: 10,
    pointy: 0,
    canvasDom: null,
    color: '#FF0000',
    name: '碎片1',
    hasAnimated: false,
    isFixed: false // 新增：标记是否已固定位置
  },
  {
    id: 2,
    src: new URL('../assets/images/photo/2.png', import.meta.url).href,
    x: 2,
    y: 408,
    pointX: 10,
    pointy: 225,
    canvasDom: null,
    color: '#00FF00',
    name: '碎片2',
    hasAnimated: false,
    isFixed: false
  },
  {
    id: 3,
    src: new URL('../assets/images/photo/3.png', import.meta.url).href,
    x: 0,
    y: 562,
    pointX: 10,
    pointy: 520,
    canvasDom: null,
    color: '#0000FF',
    name: '碎片3',
    hasAnimated: false,
    isFixed: false
  },
  {
    id: 4,
    src: new URL('../assets/images/photo/4.png', import.meta.url).href,
    x: 176,
    y: 166,
    pointX: 10,
    pointy: 775,
    canvasDom: null,
    color: '#FFFF00',
    name: '碎片4',
    hasAnimated: false,
    isFixed: false
  },
  {
    id: 5,
    src: new URL('../assets/images/photo/5.png', import.meta.url).href,
    x: 342,
    y: 0,
    pointX: 1200,
    pointy: 0,
    canvasDom: null,
    color: '#FF00FF',
    name: '碎片5',
    hasAnimated: false,
    isFixed: false
  },
  {
    id: 6,
    src: new URL('../assets/images/photo/6.png', import.meta.url).href,
    x: 314,
    y: 300,
    pointX: 1200,
    pointy: 200,
    canvasDom: null,
    color: '#00FFFF',
    name: '碎片6',
    hasAnimated: false,
    isFixed: false
  },
  {
    id: 7,
    src: new URL('../assets/images/photo/7.png', import.meta.url).href,
    x: 30,
    y: 0,
    pointX: 1200,
    pointy: 400,
    canvasDom: null,
    color: '#FF8000',
    name: '碎片7',
    hasAnimated: false,
    isFixed: false
  },
  {
    id: 8,
    src: new URL('../assets/images/photo/8.png', import.meta.url).href,
    x: 20,
    y: 0,
    pointX: 1200,
    pointy: 560,
    canvasDom: null,
    color: '#8000FF',
    name: '碎片8',
    hasAnimated: false,
    isFixed: false
  },
  {
    id: 9,
    src: new URL('../assets/images/photo/9.png', import.meta.url).href,
    x: 275,
    y: 569,
    pointX: 1200,
    pointy: 800,
    canvasDom: null,
    color: '#00FF80',
    name: '碎片9',
    hasAnimated: false,
    isFixed: false
  }
]
let offscreenCanvasExample = null
let imgBgX = 480, imgBgXIn = imgBgX + 90
let imgBgY = 0, imgBgYIn = imgBgY + 74
let aHeight = 150
let ctx = null

// 点击检测相关变量
let hitCanvas = null
let hitCtx = null
let isAnimating = false

// 创建点击检测 Canvas
function createHitCanvas() {
  hitCanvas = document.createElement('canvas')
  hitCanvas.width = 1600
  hitCanvas.height = 900
  hitCtx = hitCanvas.getContext('2d')
}

// 创建离屏canvas
async function offscreenCanvas() {
  return new Promise((resolve) => {
    if (offscreenCanvasExample) {
      resolve(offscreenCanvasExample)
    } else {
      offscreenCanvasExample = document.createElement('canvas');
      offscreenCanvasExample.width = 667;
      offscreenCanvasExample.height = 897;
      const offscreenCtx = offscreenCanvasExample.getContext('2d');
      let img = new Image();
      img.src = bg;
      img.onload = function () {
        offscreenCtx.drawImage(img, 0, 0);
        resolve(offscreenCanvasExample)
      }
    }
  })
}

// 初始化canvas
async function initCanvas() {
  ctx = myCanvas.value.getContext('2d');
  createHitCanvas(); // 创建点击检测Canvas

  let offscreenExample = await offscreenCanvas()
  ctx.drawImage(offscreenExample, 0, 0, offscreenExample.width, offscreenExample.height, imgBgX, imgBgY, offscreenExample.width, offscreenExample.height)

  for (let i = 0; i < imgBox2.length; i++) {
    const img = new Image();
    img.src = imgBox2[i].src;
    img.onload = function () {
      imgBox2[i].canvasDom = document.createElement('canvas');
      imgBox2[i].canvasDom.width = this.naturalWidth;
      imgBox2[i].canvasDom.height = this.naturalHeight;
      imgBox2[i].x = imgBox2[i].x + imgBgXIn
      imgBox2[i].y = imgBox2[i].y + imgBgYIn
      const offscreenCtx = imgBox2[i].canvasDom.getContext('2d');
      offscreenCtx.drawImage(this, 0, 0);
      createImage(imgBox2[i])
      // 在点击检测Canvas上绘制对应颜色的区域
      drawHitRegion(imgBox2[i])
    }
  }
  // 添加点击事件监听
  myCanvas.value.addEventListener('click', handleCanvasClick)
  myCanvas.value.addEventListener('mousemove', handleMouseMove)
}

// 在点击检测Canvas上绘制点击区域
function drawHitRegion(item) {
  let calcWidth = Math.floor((item.canvasDom.width * aHeight / item.canvasDom.height))
  hitCtx.fillStyle = item.color
  hitCtx.fillRect(item.pointX, item.pointy, calcWidth, aHeight)
}

// 创建图片
function createImage(item, animate = false) {
  if (animate) {
    ctx.drawImage(item.canvasDom, item.startX, item.startY);
  } else {
    let calcWidth = Math.floor((item.canvasDom.width * aHeight / item.canvasDom.height))
    ctx.drawImage(item.canvasDom, item.pointX, item.pointy, calcWidth, aHeight);
  }
}

// 处理Canvas点击事件
function handleCanvasClick(event) {
  if (isAnimating) return // 动画期间不响应点击
  const rect = myCanvas.value.getBoundingClientRect()
  const x = event.clientX - rect.left
  const y = event.clientY - rect.top
  // 获取点击检测Canvas上该位置的颜色
  const pixel = hitCtx.getImageData(x, y, 1, 1).data
  const color = `#${((1 << 24) + (pixel[0] << 16) + (pixel[1] << 8) + pixel[2]).toString(16).slice(1)}`
  // 查找对应的图片
  const clickedItem = imgBox2.find(item =>  item.color.toUpperCase() === color.toUpperCase())
  if (clickedItem) {
    console.log(`点击了: ${clickedItem.name}`)
    onImageClick(clickedItem, x, y)
  } else {
    console.log('点击了空白区域')
  }
}

// 处理鼠标移动事件（改变光标）
function handleMouseMove(event) {
  if (isAnimating) return

  const rect = myCanvas.value.getBoundingClientRect()
  const x = event.clientX - rect.left
  const y = event.clientY - rect.top

  const pixel = hitCtx.getImageData(x, y, 1, 1).data
  const color = `#${((1 << 24) + (pixel[0] << 16) + (pixel[1] << 8) + pixel[2]).toString(16).slice(1)}`

  const hoveredItem = imgBox2.find(item =>
      item.color.toUpperCase() === color.toUpperCase()
  )

  myCanvas.value.style.cursor = hoveredItem ? 'pointer' : 'default'
}

// 图片点击回调
function onImageClick(item, x, y) {
  // 高亮被点击的图片
  highlightImage(item)

  // 显示点击信息
  showClickInfo(item, x, y)

  // 可以在这里添加其他业务逻辑，比如开始动画
  if (!item.hasAnimated && !item.isFixed) {
    startPieceAnimation(item)
  } else if (item.isFixed) {
    console.log(`${item.name} 已经固定在目标位置`)
  }
}

// 高亮被点击的图片
function highlightImage(item) {
  const originalGlobalAlpha = ctx.globalAlpha

  let calcWidth, x, y;

  if (item.isFixed) {
    // 已固定的图片使用目标位置和原始尺寸
    x = item.targetX;
    y = item.targetY;
    calcWidth = item.canvasDom.width;
  } else {
    // 未固定的图片使用初始位置和缩放尺寸
    x = item.pointX;
    y = item.pointy;
    calcWidth = Math.floor((item.canvasDom.width * aHeight / item.canvasDom.height));
  }

  // 绘制半透明覆盖层
  ctx.fillStyle = 'rgba(255, 255, 0, 0.3)'
  ctx.fillRect(x, y, calcWidth, item.isFixed ? item.canvasDom.height : aHeight)

  // 绘制边框
  ctx.strokeStyle = 'yellow'
  ctx.lineWidth = 3
  ctx.strokeRect(x, y, calcWidth, item.isFixed ? item.canvasDom.height : aHeight)

  ctx.globalAlpha = originalGlobalAlpha

  // 1秒后重绘取消高亮
  setTimeout(() => {
    redrawAllImages()
  }, 1000)
}

// 显示点击信息
function showClickInfo(item, x, y) {
  ctx.fillStyle = 'white'
  ctx.font = '16px Arial'
  ctx.fillText(`点击了: ${item.name}`, 20, 30)
  ctx.fillText(`位置: (${Math.round(x)}, ${Math.round(y)})`, 20, 60)
  ctx.fillText(`状态: ${item.isFixed ? '已固定' : '可移动'}`, 20, 90)

  // 2秒后清除信息
  setTimeout(() => {
    redrawAllImages()
  }, 2000)
}

// 重新绘制所有图片
function redrawAllImages() {
  ctx.clearRect(0, 0, 1600, 900)
  ctx.drawImage(offscreenCanvasExample, 0, 0, offscreenCanvasExample.width, offscreenCanvasExample.height, imgBgX, imgBgY, offscreenCanvasExample.width, offscreenCanvasExample.height)

  imgBox2.forEach(item => {
    if (item.isFixed) {
      // 已固定的图片：使用目标位置和原始尺寸
      ctx.drawImage(item.canvasDom, item.targetX, item.targetY)
    } else {
      // 未固定的图片：使用初始位置和缩放尺寸
      let calcWidth = Math.floor((item.canvasDom.width * aHeight / item.canvasDom.height))
      ctx.drawImage(item.canvasDom, item.pointX, item.pointy, calcWidth, aHeight)
    }
  })
}

// 开始碎片动画
function startPieceAnimation(item) {
  if (item.hasAnimated || item.isFixed) return

  isAnimating = true
  item.hasAnimated = true
  item.startX = item.pointX
  item.startY = item.pointy
  item.targetX = item.x
  item.targetY = item.y

  moveAnimate(item)
}

// 动画函数
function moveAnimate(item) {
  let startTime = null;
  const duration = 1000;

  function animate(currentTime) {
    if (!startTime) {
      startTime = currentTime;
    }

    const elapsed = currentTime - startTime;
    const progress = Math.min(elapsed / duration, 1);

    // 清除画布
    ctx.clearRect(0, 0, 1600, 900);

    // 绘制背景
    ctx.drawImage(offscreenCanvasExample, 0, 0, offscreenCanvasExample.width, offscreenCanvasExample.height, imgBgX, imgBgY, offscreenCanvasExample.width, offscreenCanvasExample.height);

    // 计算当前位置
    const currentX = item.startX + (item.targetX - item.startX) * progress;
    const currentY = item.startY + (item.targetY - item.startY) * progress;

    // 计算缩放比例（从缩放尺寸过渡到原始尺寸）
    const startScale = aHeight / item.canvasDom.height;
    const targetScale = 1;
    const currentScale = startScale + (targetScale - startScale) * progress;

    const currentWidth = item.canvasDom.width * currentScale;
    const currentHeight = item.canvasDom.height * currentScale;

    // 绘制移动中的图片（带缩放动画）
    ctx.drawImage(item.canvasDom, currentX, currentY, currentWidth, currentHeight);

    // 绘制其他未动画的图片
    imgBox2.forEach(otherItem => {
      if (otherItem !== item && !otherItem.isFixed) {
        let calcWidth = Math.floor((otherItem.canvasDom.width * aHeight / otherItem.canvasDom.height))
        ctx.drawImage(otherItem.canvasDom, otherItem.pointX, otherItem.pointy, calcWidth, aHeight)
      } else if (otherItem.isFixed) {
        // 绘制已固定的图片
        ctx.drawImage(otherItem.canvasDom, otherItem.targetX, otherItem.targetY)
      }
    });

    // 更新点击检测区域（动画期间）
    updateHitRegionDuringAnimation(item, currentX, currentY, currentWidth, currentHeight);

    if (progress < 1) {
      requestAnimationFrame(animate);
    } else {
      console.log('动画完成！', item.name);
      isAnimating = false;
      item.isFixed = true; // 标记为已固定
      // 动画完成后更新点击检测区域到最终位置
      updateHitRegionAfterAnimation();
      // 重绘所有图片确保固定位置
      redrawAllImages();
    }
  }

  requestAnimationFrame(animate);
}

// 动画期间更新点击检测区域
function updateHitRegionDuringAnimation(item, currentX, currentY, currentWidth, currentHeight) {
  // 清除旧的点击区域
  hitCtx.clearRect(0, 0, 1600, 900);

  // 重新绘制所有静态区域的点击检测
  imgBox2.forEach(imgItem => {
    if (imgItem !== item && !imgItem.isFixed) {
      let calcWidth = Math.floor((imgItem.canvasDom.width * aHeight / imgItem.canvasDom.height))
      hitCtx.fillStyle = imgItem.color
      hitCtx.fillRect(imgItem.pointX, imgItem.pointy, calcWidth, aHeight)
    } else if (imgItem.isFixed) {
      // 已固定的图片使用目标位置和原始尺寸
      hitCtx.fillStyle = imgItem.color
      hitCtx.fillRect(imgItem.targetX, imgItem.targetY, imgItem.canvasDom.width, imgItem.canvasDom.height)
    }
  });

  // 绘制移动中的图片的点击区域
  hitCtx.fillStyle = item.color
  hitCtx.fillRect(currentX, currentY, currentWidth, currentHeight)
}

// 动画完成后更新点击检测区域
function updateHitRegionAfterAnimation() {
  hitCtx.clearRect(0, 0, 1600, 900);

  // 重新绘制所有点击区域
  imgBox2.forEach(imgItem => {
    if (imgItem.isFixed) {
      // 已固定的图片：使用目标位置和原始尺寸
      hitCtx.fillStyle = imgItem.color;
      hitCtx.fillRect(imgItem.targetX, imgItem.targetY, imgItem.canvasDom.width, imgItem.canvasDom.height);
    } else {
      // 未固定的图片：使用初始位置和缩放尺寸
      let calcWidth = Math.floor((imgItem.canvasDom.width * aHeight / imgItem.canvasDom.height));
      hitCtx.fillStyle = imgItem.color;
      hitCtx.fillRect(imgItem.pointX, imgItem.pointy, calcWidth, aHeight);
    }
  });
}

onMounted(() => {
  initCanvas()
})
</script>

<style scoped lang="less">
.root {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
  background-image: url("@/assets/images/bg/bg.png");
  background-repeat: no-repeat;
  background-size: cover;

  .left_box {
    width: calc((100% - 1600px) / 2);
    height: 100%;
  }

  .center_box {
    width: 1600px;
    height: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: gray;
    position: relative;

    .canvas_box {
      width: 1600px;
      height: 900px;
      position: relative;

      #myCanvas {
        width: 1600px;
        height: 900px;
        position: absolute;
        cursor: default;
      }
    }
  }

  .right_box {
    width: calc((100% - 1000px) / 2);
    height: 100%;
  }
}
</style>
